#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/listener.h>
void read_cb(struct bufferevent *bev, void *ctx)
{
        char buf[1024] = {0};
        size_t len =  bufferevent_read(bev,buf,sizeof(buf));
        if(len > 0){
                printf("buf:%s\n",buf);
                bufferevent_write(bev, buf, len);
        }
}
void write_cb(struct bufferevent *bev, void *ctx)
{
        printf("log: 发送的数据已经被发送出去了...\n");
}
void event_cb(struct bufferevent *bev, short what, void *ctx)
{
        if(what & BEV_EVENT_TIMEOUT && what & BEV_EVENT_READING){
                printf("客户端连接超时\n");
                bufferevent_free(bev);
        }else if(what & BEV_EVENT_EOF){
                printf("客户端已经断开\n");
                bufferevent_free(bev);
        }else if(what & BEV_EVENT_ERROR){
                printf("some other error\n");
                bufferevent_free(bev);
        }else if(what & BEV_EVENT_CONNECTED){
                printf("客户端主动连接成功\n");
                return;
        }else{
                printf("others\n");
        }
}
void listen_cb(
        struct evconnlistener* listener,
        evutil_socket_t cfd,
        struct sockaddr* client,int client_len, void* arg)
{
        struct sockaddr_in* addr = (struct sockaddr_in *)client;
        char ip[16] = {0};
        evutil_inet_ntop(addr->sin_family, &addr->sin_addr, ip, sizeof(ip)-1);
        printf("new client connect ip:%s port:%d\n", ip, ntohs(addr->sin_port));
       
        struct event_base* base = (struct event_base*)arg;
        struct bufferevent* bev = NULL;
        bev = bufferevent_socket_new(base,cfd,BEV_OPT_CLOSE_ON_FREE);
        if(!bev){
                printf("bufferevent_socket_new error file:%s line:%d",__FILE__,__LINE__);
                exit(1);
        }

        bufferevent_setcb(bev,read_cb,write_cb,event_cb,NULL);

        //设置超时
        //struct timeval t1 = {3, 0};
        //bufferevent_set_timeouts(bev, &t1, 0);

        int ret = bufferevent_enable(bev, EV_READ|EV_WRITE);
        if(ret == -1){
                printf("bufferevent_enable error file:%s line:%d",__FILE__,__LINE__);
                exit(1);
        }
}
int main(int argc, char const *argv[])
{
        struct event_base* base = NULL;
        base = event_base_new(); 
        if(!base){
                printf("event_base_new error file:%s line:%d",__FILE__,__LINE__);
                exit(1);
        }

        struct evconnlistener* lev = NULL;
        struct sockaddr_in serv;
        memset(&serv,0,sizeof(serv));
        serv.sin_family = AF_INET;
        serv.sin_port = htons(8765);
        serv.sin_addr.s_addr = htonl(INADDR_ANY);
        lev = evconnlistener_new_bind(
                base,
                listen_cb,
                base, 
                LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
                -1,
                (struct sockaddr *)&serv,
                sizeof(serv));
        if(!lev){
                goto __ERROR__;
        }

        int ret = event_base_dispatch(base);
        if(ret == -1){
                goto __ERROR__;
        }

__ERROR__:
        if(lev){
                evconnlistener_free(lev);
        }
        if(base){
                event_base_free(base);
        }
        return 0;
}
